{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install openai==0.28"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "# Load environment variables from openai.env file\n",
    "load_dotenv(\"openai.env\")\n",
    "\n",
    "# Read the OPENAI_API_KEY from the environment\n",
    "api_key = os.getenv(\"OPENAI_API_KEY\")\n",
    "api_base = os.getenv(\"OPENAI_API_BASE\")\n",
    "os.environ[\"OPENAI_API_KEY\"] = api_key\n",
    "os.environ[\"OPENAI_API_BASE\"] = api_base"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 如何加载使用tool\n",
    "- 加载预制tool的方法\n",
    "- 几种tool的使用方式\n",
    "<hr>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "langchain预制了大量的tools，基本这些工具能满足大部分需求，https://github.com/langchain-ai/langchain/tree/v0.0.352/docs/docs/integrations/tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Got unknown tool Ellipsis",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[2], line 4\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01magents\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m load_tools\n\u001b[1;32m      3\u001b[0m tool_names \u001b[38;5;241m=\u001b[39m [\u001b[38;5;241m.\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;241m.\u001b[39m]\n\u001b[0;32m----> 4\u001b[0m tools \u001b[38;5;241m=\u001b[39m \u001b[43mload_tools\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtool_names\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m#使用load方法\u001b[39;00m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;66;03m#有些tool需要单独设置llm\u001b[39;00m\n\u001b[1;32m      6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01magents\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m load_tools\n",
      "File \u001b[0;32m~/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain/agents/load_tools.py:678\u001b[0m, in \u001b[0;36mload_tools\u001b[0;34m(tool_names, llm, callbacks, allow_dangerous_tools, **kwargs)\u001b[0m\n\u001b[1;32m    676\u001b[0m         tools\u001b[38;5;241m.\u001b[39mappend(tool)\n\u001b[1;32m    677\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 678\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGot unknown tool \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m    679\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m callbacks \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m    680\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m tool \u001b[38;5;129;01min\u001b[39;00m tools:\n",
      "\u001b[0;31mValueError\u001b[0m: Got unknown tool Ellipsis"
     ]
    }
   ],
   "source": [
    "#添加预制工具的方法很简单\n",
    "from langchain.agents import load_tools\n",
    "tool_names = [...]\n",
    "tools = load_tools(tool_names) #使用load方法\n",
    "#有些tool需要单独设置llm\n",
    "from langchain.agents import load_tools\n",
    "tool_names = [...]\n",
    "llm = ...\n",
    "tools = load_tools(tool_names, llm=llm) #在load的时候指定llm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SerpAPI\n",
    "最常见的聚合搜索引擎 https://serper.dev/dashboard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.utilities import SerpAPIWrapper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "#serpapi的api key\n",
    "import os\n",
    "os.environ[\"SERPAPI_API_KEY\"] = \"f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "search = SerpAPIWrapper()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Got error from SerpAPI: Your account has run out of searches.",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msearch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mObama\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43ms first name?\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain_community/utilities/serpapi.py:84\u001b[0m, in \u001b[0;36mSerpAPIWrapper.run\u001b[0;34m(self, query, **kwargs)\u001b[0m\n\u001b[1;32m     82\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrun\u001b[39m(\u001b[38;5;28mself\u001b[39m, query: \u001b[38;5;28mstr\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28mstr\u001b[39m:\n\u001b[1;32m     83\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"Run query through SerpAPI and parse result.\"\"\"\u001b[39;00m\n\u001b[0;32m---> 84\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_process_response\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresults\u001b[49m\u001b[43m(\u001b[49m\u001b[43mquery\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain_community/utilities/serpapi.py:130\u001b[0m, in \u001b[0;36mSerpAPIWrapper._process_response\u001b[0;34m(res)\u001b[0m\n\u001b[1;32m    128\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Process response from SerpAPI.\"\"\"\u001b[39;00m\n\u001b[1;32m    129\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124merror\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m res\u001b[38;5;241m.\u001b[39mkeys():\n\u001b[0;32m--> 130\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGot error from SerpAPI: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mres[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124merror\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m    131\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124manswer_box_list\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m res\u001b[38;5;241m.\u001b[39mkeys():\n\u001b[1;32m    132\u001b[0m     res[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124manswer_box\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m res[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124manswer_box_list\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n",
      "\u001b[0;31mValueError\u001b[0m: Got error from SerpAPI: Your account has run out of searches."
     ]
    }
   ],
   "source": [
    "search.run(\"Obama's first name?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "支持自定义参数，比如将引擎切换到bing，设置搜索语言等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "params = {\n",
    "    \"engine\": \"bing\",\n",
    "    \"gl\": \"us\",\n",
    "    \"hl\": \"en\",\n",
    "}\n",
    "search = SerpAPIWrapper(params=params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "search.run(\"Obama's first name?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用Dall-E\n",
    "Dall-E是openai出品的文到图AI大模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install opencv-python scikit-image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model=\"gpt-4\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import initialize_agent, load_tools\n",
    "\n",
    "tools = load_tools([\"dalle-image-generator\"])\n",
    "agent = initialize_agent(\n",
    "    tools, \n",
    "    llm, \n",
    "    agent=\"zero-shot-react-description\",\n",
    "    verbose=True\n",
    ")\n",
    "output = agent.run(\"Create an image of a halloween night at a haunted museum\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Eleven Labs Text2Speech\n",
    "ElevenLabs 是非常优秀的TTS合成API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install elevenlabs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install --upgrade pydantic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "插入APIKEY"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"ELEVEN_API_KEY\"] = \"23261e4a3b79697822252a505a169863\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "工具使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.tools import ElevenLabsText2SpeechTool\n",
    "\n",
    "text_to_speak = \"Hello! 你好! Hola! नमस्ते! Bonjour! こんにちは! مرحبا! 안녕하세요! Ciao! Cześć! Привіт! வணக்கம்!\"\n",
    "\n",
    "tts = ElevenLabsText2SpeechTool(\n",
    "    voice=\"Bella\",\n",
    "    text_to_speak=text_to_speak,\n",
    "    verbose=True\n",
    ")\n",
    "tts.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "speech_file = tts.run(text_to_speak)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#tts.play(speech_file)\n",
    "tts.stream_speech(text_to_speak)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GraphQL\n",
    "一种api查询语言，类似sql，我们用它来查询奈飞的数据库，查找一下和星球大战相关的电影，API地址https://swapi-graphql.netlify.app/.netlify/functions/index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install httpx gql > /dev/null"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install gql"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install requests_toolbelt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/tomiezhang/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.chat_models.openai.ChatOpenAI` was deprecated in langchain-community 0.0.10 and will be removed in 0.2.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import ChatOpenAI`.\n",
      "  warn_deprecated(\n",
      "/Users/tomiezhang/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `initialize_agent` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use Use new agent constructor methods like create_react_agent, create_json_agent, create_structured_chat_agent, etc. instead.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.agents import load_tools, initialize_agent, AgentType\n",
    "from langchain.utilities import GraphQLAPIWrapper\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model=\"gpt-4\",\n",
    "    )\n",
    "\n",
    "tools = load_tools(\n",
    "    [\"graphql\"],\n",
    "    graphql_endpoint=\"https://swapi-graphql.netlify.app/.netlify/functions/index\",\n",
    ")\n",
    "\n",
    "agent = initialize_agent(\n",
    "    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/tomiezhang/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `run` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n",
      "  warn_deprecated(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mTo answer this question, I need to query the GraphQL database for all the Star Wars films and their titles. I will use the provided schema to construct the query. After getting the titles, I will translate them into Chinese.\n",
      "\n",
      "Action: query_graphql\n",
      "Action Input: query { allFilms { films { title } } }\u001b[0m\n",
      "Observation: \u001b[36;1m\u001b[1;3m\"{\\n  \\\"allFilms\\\": {\\n    \\\"films\\\": [\\n      {\\n        \\\"title\\\": \\\"A New Hope\\\"\\n      },\\n      {\\n        \\\"title\\\": \\\"The Empire Strikes Back\\\"\\n      },\\n      {\\n        \\\"title\\\": \\\"Return of the Jedi\\\"\\n      },\\n      {\\n        \\\"title\\\": \\\"The Phantom Menace\\\"\\n      },\\n      {\\n        \\\"title\\\": \\\"Attack of the Clones\\\"\\n      },\\n      {\\n        \\\"title\\\": \\\"Revenge of the Sith\\\"\\n      }\\n    ]\\n  }\\n}\"\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI have retrieved the titles of all the Star Wars films from the GraphQL database. Now I need to translate these titles into Chinese.\n",
      "\n",
      "Action: translate\n",
      "Action Input: [\"A New Hope\", \"The Empire Strikes Back\", \"Return of the Jedi\", \"The Phantom Menace\", \"Attack of the Clones\", \"Revenge of the Sith\"]\u001b[0m\n",
      "Observation: translate is not a valid tool, try one of [query_graphql].\n",
      "Thought:\u001b[32;1m\u001b[1;3mI made a mistake. I don't have a tool to translate the titles into Chinese. I will provide the titles in English.\n",
      "Final Answer: The titles of the Star Wars films are \"A New Hope\", \"The Empire Strikes Back\", \"Return of the Jedi\", \"The Phantom Menace\", \"Attack of the Clones\", and \"Revenge of the Sith\".\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'The titles of the Star Wars films are \"A New Hope\", \"The Empire Strikes Back\", \"Return of the Jedi\", \"The Phantom Menace\", \"Attack of the Clones\", and \"Revenge of the Sith\".'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graphql_fields = \"\"\"allFilms {\n",
    "    films {\n",
    "      title\n",
    "      director\n",
    "      releaseDate\n",
    "      speciesConnection {\n",
    "        species {\n",
    "          name\n",
    "          classification\n",
    "          homeworld {\n",
    "            name\n",
    "          }\n",
    "        }\n",
    "      }\n",
    "    }\n",
    "  }\n",
    "\n",
    "\"\"\"\n",
    "\n",
    "suffix = \"Search for the titles of all the stawars films stored in the graphql database that has this schema,and answer in chinese:\"\n",
    "\n",
    "\n",
    "agent.run(suffix + graphql_fields)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchains",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
     